package com.scexample.template;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson.JSON;
import com.scexample.builder.TemplateBuilder;
import com.scexample.common.ErrorCode;
import com.scexample.common.PayTypeEnum;
import com.scexample.common.Result;
import com.scexample.exception.BusinessException;
import com.scexample.pojo.*;
import com.scexample.service.MerchantService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.InputStream;
import java.net.URL;
import java.util.Objects;

/**
 * @program: scexample
 * @description: 聚合进件template
 * @author: 少男
 * @create: 2021-01-18 15:22
 **/
@Slf4j
public final class PayMerchantTemplate extends AbstractMerchantTemplate {

    private MerchantService merchantService;
    private MerchantConfigContext configContext;
    private TemplateBuilder templateBuilder;
    private ApplicationContext applicationContext;

    public PayMerchantTemplate(MerchantService merchantService, ApplicationContext applicationContext, Byte platformCode, TemplateBuilder templateBuilder) {
        super(platformCode);
        this.templateBuilder = templateBuilder;
        this.merchantService = merchantService;
        this.configContext = getMerchantConfigContext();
        // 占位使用，灵活传入可利用ioc容器内的bean
        this.applicationContext = applicationContext;
    }

    @Override
    public <T extends PublicModel> Result<String> apply(@NotNull(message = "进件申请入参不可为空") GenericShop<T> transferDTO) {
        T valueTransfer;
        if (Objects.isNull(valueTransfer = transferDTO.getParam()) || StrUtil.isBlank(transferDTO.getShopName())) {
            return Result.error(ErrorCode.S400.statusCode(), "进件申请入参不可为空");
        }

        try {
            MerchantDTO targetTransfer = (MerchantDTO) valueTransfer;
            BeanUtil.copyProperties(this.configContext, targetTransfer);
            Result<String> stringResult = beforePrintLog(merchantService.merchantCreate(sign(targetTransfer, "门店进件申请")), "门店进件申请");
            if (stringResult.isStatus()) {
                return stringResult;
            }
        } finally {
            super.remove();
            templateBuilder.close();
        }
        return Result.error(ErrorCode.S501.statusCode(), "进件申请流程异常");
    }

    @Override
    public <T extends PublicModel> Result<String> update(T transferDTO) {
        if (Objects.isNull(transferDTO)) {
            return new Result<>();
        }

        Result<String> stringResult;
        try {
            MerchantDTO targetCreate = (MerchantDTO) transferDTO;
            BeanUtil.copyProperties(this.configContext, targetCreate);
            stringResult = beforePrintLog(merchantService.merchantModify(sign(targetCreate, "进件申请修改")), "进件申请修改");
        } finally {
            super.remove();
            templateBuilder.close();
        }
        return stringResult;
    }

    @Override
    public <T extends PublicModel> Result<MerchantQueryVo> query(@NotNull(message = "进件查询入参不可为空") T transferDTO) {
        MerchantQueryDTO targetCreate = (MerchantQueryDTO) transferDTO;
        BeanUtil.copyProperties(this.configContext, targetCreate);
        Result<MerchantQueryVo> result = beforePrintLog(merchantService.merchantQuery(sign(targetCreate, "财金进件查询")), "财金进件查询");
        super.remove();
        templateBuilder.close();
        return result;
    }

    @Override
    public <T extends PublicModel> Result<Boolean> bind(T transferDTO) {
        if (Objects.isNull(transferDTO)) {
            return new Result<>();
        }
        Result<Boolean> booleanResult;
        try {
            BindCardDTO targetCreate = (BindCardDTO) transferDTO;
            BeanUtil.copyProperties(this.configContext, targetCreate);
            booleanResult = beforePrintLog(merchantService.bindCard(sign(targetCreate, "进件绑卡")), "进件绑卡");
        } finally {
            super.remove();
            templateBuilder.close();
        }
        return booleanResult;
    }

    @Override
    public <T extends PublicModel> T sign(T transferDTO, String logContent) {
        T signResult = sign(transferDTO);
        log.debug(logContent + "业务签名后完整入参：{}", JSON.toJSONString(signResult, true));
        return signResult;
    }

    @Override
    public <T extends PublicModel> T sign(T transferDTO) {
        transferDTO.setSign(getSignNew(transferDTO, transferDTO.getSceneCode(), "PRIVATE_KEY"));
        return transferDTO;
    }

    @Override
    public <T extends PublicModel> Result<String> uploadImg(@NotNull(message = "财金附件上传信息不可为空") T transferDTO) {
        Result<String> stringResult;
        try {
            MerchantImageDTO imageDTO = (MerchantImageDTO) transferDTO;
            BeanUtil.copyProperties(this.configContext, imageDTO);
            byte[] tempContent = imageDTO.getImageContent();
            imageDTO.setImageContent(null);
            MerchantImageDTO tempDTO = sign(imageDTO, "进件图片上传");

            if (tempContent.length > 0) {
                tempDTO.setImageContent(tempContent);
            }
            stringResult = beforePrintLog(merchantService.uploadImg(tempDTO), "普通进件附件上传");
        } finally {
            super.remove();
            templateBuilder.close();
        }
        return stringResult;
    }

    /**
     * @param payCode   进件方式，目前支持支付宝、微信
     * @param fileName  目标存储文件名称
     * @param filePath  仅支持http或https url图片资源地址
     * @param imageType 图片类型，支付宝必须传入，微信可选
     * @return 上传返回字符串，用于进件相关属性赋值使用
     * @author: youngBoy
     * 支持http url图片地址转换为字节方式调用财金进件附件上传
     */
    public Result<String> uploadImg(@NotNull(message = "进件支付方式不可为空") Byte payCode,
                                    @NotBlank(message = "进件附件上传文件名不可为空") String fileName,
                                    @NotBlank(message = "进件附件文件路径不可为空") String filePath, String imageType) {
        if (PayTypeEnum.aliPay.getCode().equals(payCode)) {
            if (StrUtil.isBlank(imageType)) {
                return Result.error(ErrorCode.S400.statusCode(), "支付宝进件附件上传文件类型不可为空");
            }
        }
        Result<String> stringResult = Result.error(ErrorCode.S501.statusCode(), "进件附件上传失败");
        if (filePath.startsWith("http")) {
            try (InputStream stream = URLUtil.getStream(new URL(filePath))) {
                byte[] bytes = IoUtil.readBytes(stream);
                MerchantImageDTO merchantImageDTO = new MerchantImageDTO();
                merchantImageDTO.setImageName(fileName);
                merchantImageDTO.setImageType(imageType);
                BeanUtil.copyProperties(this.configContext, merchantImageDTO);
                merchantImageDTO = sign(merchantImageDTO, "进件附件上传");
                merchantImageDTO.setImageContent(bytes);

                stringResult = beforePrintLog(merchantService.uploadImg(merchantImageDTO), "url方式进件附件上传");
            } catch (Exception e) {
                log.error("图片上传错误日志内容:{},{},{}", e, e.getMessage(), e.getStackTrace());
                return Result.error(ErrorCode.S500.statusCode(), "进件附件上传错误");
            } finally {
                super.remove();
                templateBuilder.close();
            }
        }
        return stringResult;
    }

    private <T> Result<T> beforePrintLog(Result<T> result, String logContent) {
        log.debug(logContent + "业务签名后完整出参：{}", JSON.toJSONString(result, true));
        return result;
    }

    private String[] preCheck(MerchantDTO targetTransfer) {
        String shopNo = "", custAccount = "";
        if (Objects.equals(PayTypeEnum.aliPay.getCode(), configContext.getPayPlatformCode())) {

        } else if (Objects.equals(PayTypeEnum.wxPay.getCode(), configContext.getPayPlatformCode())) {
        } else {
            throw new BusinessException(ErrorCode.S501.statusCode(), "暂不支持其他支付方式进件申请");
        }
        return new String[]{shopNo, custAccount};
    }

    private String getSignNew(Object object, String sceneCode, String privateKey) {
        return "SECRET";
    }
}
